package src;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;


public class CommUtil implements Runnable {
	private final static int rcvPort = 4000;
	ServerSocket listenSocket;
	static Main m;
	PrintWriter socketOutput;
	static HashMap socketList;
	private final int sendPort = 3000;
	
	
	public CommUtil(Main m) throws IOException {
			listenSocket = new ServerSocket(rcvPort);
			this.m = m;

	}
	
	public static void connectToNodes() throws Exception {
		ArrayList<Node> nodes = Nodelist.getNodes();
		for(int i=0; i < nodes.size(); i++) {
			// Checks that node is not itself, and connects.
			if(!nodes.get(i).getAddress().equals(InetAddress.getLocalHost())) {
				Socket s = new Socket(nodes.get(i).getAddress(), rcvPort);
				System.out.println("Successfully connected to node " + nodes.get(i).getHostname());
				socketList.put(nodes.get(i).getId(), s);
			}
		}
	}
	
	public void closeSockets()  {
		
		try {
			listenSocket.close();
		}
		catch (IOException e) {
		}
		Iterator socketIterator = socketList.values().iterator();
		while (socketIterator.hasNext()) {
			try {
				Socket s = (Socket)socketIterator.next();
				s.close();
			}
			catch (IOException e) {
			}	
		}
	}
	
	public void acceptConnections(){
		socketList = new HashMap<Integer, Socket>();
		while(true) {
			Socket socket = null;
			try {
				socket = listenSocket.accept();
				System.out.println("Connection from " + socket.getInetAddress().getHostName() + " accepted");
				if(!socketList.containsKey(socket.getInetAddress().getHostName())) {
					socketList.put(socket.getInetAddress().getHostName(), socket);
					CommRcv rcv = new CommRcv(socket, m);
						Thread t = new Thread(rcv);
						t.start();
				}

			} catch (IOException e) {
				
			}

		}

	}
	
	public void send(String msg, int nodeid, TimeTable timetable) throws UnknownHostException, IOException {
		if(nodeid != m.getNodeID()) {
			Socket socket = (Socket)socketList.get(nodeid);
			socketOutput = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
			socketOutput.println(msg+"Timetable:"+timetable.toString());
			System.out.println("Msg: " + msg + " sent to node: " + nodeid);
		}
		else {
			System.out.println("Why do you wanna send a msg to yourself?");
		}
	}


	@Override
	public void run() {
		System.out.println("[Setup]: Starts accepting connections.");
		System.out.println("[Setup]: Type 'connect' to connect to other nodes.");
		System.out.println("[Setup]: Type 'list' to list 'key = value' pairs in the dictionary.");
		System.out.println("[Setup]: Type 'send x ' to send a message with the log to node x.");
		System.out.println("[Setup]: Type 'insert x y' to insert key x and value y to the dictionary.");
		System.out.println("[Setup]: Type 'delete x ' to delete key x from the dictionary.");
		System.out.println("[Setup]: Type 'exit ' to close all connections and exit the program.");
	


		acceptConnections();
		
	}
	


}
